﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Runtime.CompilerServices;

namespace LowLevelGraphics
{
    /// <summary>
    /// 
    /// </summary>
    public static class RectangleExtension
    {
        /// <summary>
        /// Intersectses the with inclusive.
        /// </summary>
        /// <param name="r">The r.</param>
        /// <param name="r2">The r2.</param>
        /// <returns></returns>
        public static bool IntersectsWithInclusive(this Rectangle r, Rectangle r2)
        {
            return !((r.Left > r2.Right) || (r.Right < r2.Left) ||
                (r.Top > r2.Bottom) || (r.Bottom < r2.Top));
        }

        /// <summary>
        /// Centers the specified r.
        /// </summary>
        /// <param name="r">The r.</param>
        /// <returns></returns>
        public static Point Center(this Rectangle r)
        {
            return new Point(r.Left + r.Width / 2, r.Top + r.Height / 2);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public static class RectangleHelpers
    {
        #region Methods
        /// <summary>
        /// Draws the reversible rectangle.
        /// </summary>
        /// <param name="p1">The p1.</param>
        /// <param name="p2">The p2.</param>
        /// <returns></returns>
        public static Rectangle CalcRectangle(Point p1, Point p2)
        {
            Rectangle rc = new Rectangle();
            if (p1.X < p2.X)
            {
                rc.X = p1.X;
                rc.Width = p2.X - p1.X;
            }
            else
            {
                rc.X = p2.X;
                rc.Width = p1.X - p2.X;
            }
            if (p1.Y < p2.Y)
            {
                rc.Y = p1.Y;
                rc.Height = p2.Y - p1.Y;
            }
            else
            {
                rc.Y = p2.Y;
                rc.Height = p1.Y - p2.Y;
            }

            return rc;
        }

        /// <summary>
        /// Centers the specified r.
        /// </summary>
        /// <param name="r">The r.</param>
        /// <returns></returns>
        public static Point Center(Rectangle r)
        {
            return new Point(r.Left + r.Width / 2, r.Top + r.Height / 2);
        }

        /// <summary>
        /// Joins the specified _enum.
        /// </summary>
        /// <param name="_enum">The _enum.</param>
        /// <returns></returns>
        public static Rectangle Join(IEnumerable<Rectangle> _enum)
        {
            IEnumerator enumerator = _enum.GetEnumerator();
            Rectangle rectCurrent = Rectangle.Empty;
            Rectangle rectNextCurrent = Rectangle.Empty;
            Rectangle rectResult = Rectangle.Empty;
            while (enumerator.MoveNext())
            {
                if (enumerator.Current is Rectangle)
                {
                    rectCurrent = (Rectangle)enumerator.Current;
                }
                else
                {
                    //rectCurrent = (Point)enumerator.Current;
                }
                if (enumerator.MoveNext())
                {
                    rectNextCurrent = (Rectangle)enumerator.Current;
                }
                rectResult = Rectangle.Union(rectResult, Rectangle.Union(rectCurrent, rectNextCurrent));
            }
            return rectResult;
        }

        /// <summary>
        /// Joins the specified _enum.
        /// </summary>
        /// <param name="_enum">The _enum.</param>
        /// <returns></returns>
        public static Rectangle Join(IEnumerable<Point> _enum)
        {
            Rectangle rectResult = Rectangle.Empty;
            Point ptCurrent = new Point(-1,-1);

            IEnumerator enumerator = _enum.GetEnumerator();

            Point ptStart = new Point(-1,-1);
            Point ptEnd = new Point(-1,-1);
            if (enumerator.MoveNext())
            {
                ptStart = (Point)enumerator.Current;
            }

            if (enumerator.MoveNext())
            {
                ptEnd = (Point)enumerator.Current;
            }

            rectResult = CalcRectangle(ptStart, ptEnd);

            if (rectResult == Rectangle.Empty) return rectResult;

            while (enumerator.MoveNext())
            {
                ptCurrent = (Point)enumerator.Current;
                rectResult = Join(rectResult, ptCurrent);
            }
            return rectResult;
        }

        /// <summary>
        /// Joins the specified rect.
        /// </summary>
        /// <param name="rect">The rect.</param>
        /// <param name="_enum">The _enum.</param>
        /// <returns></returns>
        public static Rectangle Join(Rectangle rect, IEnumerable<Point> _enum)
        {
            IEnumerator enumerator = _enum.GetEnumerator();
            Point ptCurrent = new Point(-1,-1);
            Point ptNextCurrent = new Point(-1, -1);
            Rectangle rectResult = Rectangle.Empty;
            while (enumerator.MoveNext())
            {
                ptCurrent = (Point)enumerator.Current;
                if (enumerator.MoveNext())
                {
                    ptNextCurrent = (Point)enumerator.Current;
                }
                rectResult = Rectangle.Union(rectResult, CalcRectangle(rectResult.Location, ptCurrent));
            }
            return rectResult;
        }

        /// <summary>
        /// Joins the specified rect.
        /// </summary>
        /// <param name="rect">The rect.</param>
        /// <param name="pt">The pt.</param>
        /// <returns></returns>
        public static Rectangle Join(Rectangle rect, Point pt)
        {
            if (!rect.Contains(pt))
            {
                return CalcRectangle(rect.Location, pt);
            }
            return rect;
        }

        /// <summary>
        /// Gets the rectangle from point array.
        /// </summary>
        /// <param name="aPoint">A point.</param>
        /// <returns></returns>
        public static Rectangle GetRectangleFromPointArray(List<Point> aPoint)
        {
            int nX1 = 0;
            int nX2 = 0;
            int nY1 = 0;
            int nY2 = 0;

            if (aPoint.Count > 0)
            {
                aPoint.Sort(new PointSort(PointSort.Mode.X));

                nX1 = aPoint[0].X;
                nX2 = aPoint[aPoint.Count - 1].X;
                Point pt1 = new Point(nX1, nY1);

                aPoint.Sort(new PointSort(PointSort.Mode.Y));

                nY1 = aPoint[0].Y;
                nY2 = aPoint[aPoint.Count - 1].Y;
                Point pt2 = new Point(nX2, nY2);

                return RectangleHelpers.CalcRectangle(pt1, pt2);
            }
            return Rectangle.Empty;
        }

        #endregion Methods
    }
}
